package com.g4.shoppingback.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 开启资源访问验证和权限验证
 */
@Configuration
@EnableResourceServer   //开启资源访问验证
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限验证,开启方法验证
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //super.configure(http);
        //http.cors().and().csrf().disable().authorizeRequests().antMatchers("/shoppingback/ddUsersInfo").authenticated().anyRequest().permitAll();
        http.cors().and().csrf().disable().authorizeRequests().anyRequest().authenticated().and() //所有请求都需要验证
        .exceptionHandling().accessDeniedHandler(accessDeniedHandler()).and() //权限异常处理
        .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()); //访问异常处理
    }

    /**
     * 自定义权限异常处理
     * @return
     */
    private AccessDeniedHandler accessDeniedHandler() {
        return new AccessDeniedHandler() {
            @Override
            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
                Map<String, Object> map = new HashMap<>();
                map.put("status", HttpServletResponse.SC_FORBIDDEN);//SC_FORBIDDEN的值是403
                map.put("msg", "该请求被拒绝访问,因为没有权限");
                //1设置响应数据的编码
                httpServletResponse.setCharacterEncoding("utf-8");
                //2告诉浏览器响应数据的内容类型以及编码
                httpServletResponse.setContentType("application/json;charset=utf-8");
                //3获取输出流对象
                PrintWriter out=httpServletResponse.getWriter(); //自定义输出内容
                //4 输出数据
                String result= new ObjectMapper().writeValueAsString(map); //转换成json输出
                out.println(result);
                out.flush();    //刷新缓冲区，流对象可以继续使用
                //out.close();   //先刷新缓冲区，然后通知系统释放资源。流对象不能再被使用了。
            }
        };
    }

    /**
     * 自定义访问异常处理
     * @return
     */
    private AuthenticationEntryPoint authenticationEntryPoint() {
        return new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                Map<String, Object> map = new HashMap<>();
                map.put("state", HttpServletResponse.SC_UNAUTHORIZED);//SC_UNAUTHORIZED是401
                map.put("message", "该请求被拒绝访问,需要身份验证");
                //1设置响应数据的编码
                httpServletResponse.setCharacterEncoding("utf-8");
                //2告诉浏览器响应数据的内容类型以及编码
                httpServletResponse.setContentType("application/json;charset=utf-8");
                //3获取输出流对象
                PrintWriter out=httpServletResponse.getWriter();
                //4 输出数据
                String result= new ObjectMapper().writeValueAsString(map);
                out.println(result);
                out.flush();
                //out.close();
            }
        };
    }
}
